#ifndef _HTABLE_H_
#define _HTABLE_H_
#include <stdlib.h>
#include "list.h"

#define HTABLE_SIZE (2 << 20) /* 2M list headers */
#define which_head(tabel, key) (&table->header[key->key % HTABLE_SIZE])
struct hkey
{
	unsigned long long key; /* must be unsigned */
	struct list_head link;
}  __attribute__ ((packed));
struct htable
{
	struct list_head *header;
};

static inline void make_key(struct hkey *key, unsigned long long keyval)
{
	INIT_LIST_HEAD(&key->link);
	key->key = keyval;
}

static inline int htable_init(struct htable *table)
{
	int i;
	if ((table->header = malloc(sizeof(struct list_head)*HTABLE_SIZE)) == 0)
		return -1;
	for (i=0; i<HTABLE_SIZE; i++)
		INIT_LIST_HEAD(&table->header[i]);
	return 1;
}

static inline void htable_add(struct htable *table, struct hkey *key)
{
	list_add(&key->link, which_head(table, key));
}

static inline struct hkey* htable_find(struct htable *table, struct hkey *key)
{
	struct list_head *head = which_head(table, key);
	struct list_head *curh = head->next;
	struct hkey *curk; 
	while (curh != head)
	{
		curk = container_of(curh, struct hkey, link);
		if (curk->key == key->key)
			return curk;
		curh = curh->next;
	}
	return 0;
}

static inline void htable_del(struct htable *table, struct hkey *key)
{
	list_del(&key->link);
}

#endif
